import { PrismaClient } from '@prisma/client'
import { formatBeijingTime, getBeijingStartOfDay } from '../utils/timezone'

const REQUIRED_NOTE = `
环境变量支持：
  TARGET_DATE=YYYY-MM-DD   指定需要检查的北京时间（默认今天）
  INSPECT_USER_ID=<number> 指定单个用户 ID，额外输出其收益进度

运行示例：
  bunx tsx scripts/testRewardDistribution.ts
  TARGET_DATE=2025-11-05 INSPECT_USER_ID=803 bunx tsx scripts/testRewardDistribution.ts
`

const prisma = new PrismaClient()

interface StakingSnapshot {
  userId: number
  dailyDistributionCount: number
  dailyRewardDistributed: number
  currentDailyReward: number
  nextDistributionAt: Date | null
  lastSettlementDate: Date | null
}

const toBeijingDateLabel = (date: Date): string => {
  return new Date(date.getTime() + 8 * 60 * 60 * 1000)
    .toISOString()
    .slice(0, 10)
}

const parseTargetDate = (): Date => {
  const targetDateEnv = process.env.TARGET_DATE
  if (!targetDateEnv) {
    return new Date()
  }

  const parsed = new Date(`${targetDateEnv}T00:00:00+08:00`)
  if (Number.isNaN(parsed.getTime())) {
    throw new Error(`无法解析 TARGET_DATE=${targetDateEnv}，请使用 YYYY-MM-DD 格式`)
  }
  return parsed
}

const main = async (): Promise<void> => {
  console.log('🚀 收益发放进度检测脚本（仅查询，不修改数据）')
  console.log(REQUIRED_NOTE)

  try {
    const targetDate = parseTargetDate()
    const dayStart = getBeijingStartOfDay(targetDate)
    const beijingLabel = toBeijingDateLabel(dayStart)

    console.log(`
📅 检查自然日（北京时间）: ${beijingLabel}`)

    let status = await prisma.rewardDistributionStatus.findUnique({
      where: { date: dayStart }
    })

    if (!status) {
      const fallbackStart = new Date(dayStart.getTime() - 12 * 60 * 60 * 1000)
      const fallbackEnd = new Date(dayStart.getTime() + 12 * 60 * 60 * 1000)

      status = await prisma.rewardDistributionStatus.findFirst({
        where: {
          date: {
            gte: fallbackStart,
            lt: fallbackEnd
          }
        },
        orderBy: { date: 'asc' }
      })

      if (!status) {
        console.log('⚠️ reward_distribution_statuses 暂无该日记录，可能当天尚未初始化。')
        return
      }

      console.log('ℹ️ 未匹配到严格的北京时间 0 点记录，已在 ±12 小时窗口内找到最接近的记录。')
    }

    console.log(`状态摘要：`)
    console.log(`  已发次数          : ${status.distributionCount}`)
    console.log(`  上次发放时间      : ${status.lastDistributionAt ? formatBeijingTime(status.lastDistributionAt) : '无记录'}`)
    console.log(`  下一次计划发放时间: ${status.nextDistributionAt ? formatBeijingTime(status.nextDistributionAt) : '无计划'}`)

    const activeStakings = await prisma.userStaking.findMany({
      where: {
        OR: [
          { stakedAmount: { gt: 0 } },
          { lockedAmount: { gt: 0 } }
        ]
      },
      select: {
        userId: true,
        dailyDistributionCount: true,
        dailyRewardDistributed: true,
        currentDailyReward: true,
        nextDistributionAt: true,
        lastSettlementDate: true
      }
    })

    const snapshots: StakingSnapshot[] = activeStakings.map((staking) => ({
      userId: staking.userId,
      dailyDistributionCount: staking.dailyDistributionCount,
      dailyRewardDistributed: Number(staking.dailyRewardDistributed),
      currentDailyReward: Number(staking.currentDailyReward),
      nextDistributionAt: staking.nextDistributionAt,
      lastSettlementDate: staking.lastSettlementDate
    }))

    const totalUsers = snapshots.length
    const completedUsers = snapshots.filter(s => s.dailyDistributionCount >= status.distributionCount).length
    const aheadUsers = snapshots.filter(s => s.dailyDistributionCount > status.distributionCount).length
    const behindUsers = snapshots.filter(s => s.dailyDistributionCount < status.distributionCount).length

    console.log(`
用户发放进度统计（基于 user_staking.daily_distribution_count ）：`)
    console.log(`  总用户数  : ${totalUsers}`)
    console.log(`  已对齐用户: ${completedUsers}`)
    console.log(`  超前用户  : ${aheadUsers}`)
    console.log(`  落后用户  : ${behindUsers}`)

    if (behindUsers > 0) {
      const sample = snapshots
        .filter(s => s.dailyDistributionCount < status.distributionCount)
        .slice(0, 10)

      console.log(`
  ⚠️ 落后样例（最多显示 10 个）：`)
      sample.forEach((item) => {
        console.log(
          `    - 用户 ${item.userId}: 已发 ${item.dailyDistributionCount}/${status.distributionCount} 次, ` +
          `当日收益 ${item.currentDailyReward.toFixed(4)} NEAR, ` +
          `已发金额 ${item.dailyRewardDistributed.toFixed(4)} NEAR, ` +
          `下一次发放: ${item.nextDistributionAt ? formatBeijingTime(item.nextDistributionAt) : '未安排'}`
        )
      })
    }

    const inspectUserIdEnv = process.env.INSPECT_USER_ID
    if (inspectUserIdEnv) {
      const userId = Number(inspectUserIdEnv)
      if (Number.isNaN(userId)) {
        console.warn(`INSPECT_USER_ID=${inspectUserIdEnv} 无法解析为数字，跳过个别用户展示。`)
      } else {
        const userSnapshot = snapshots.find(s => s.userId === userId)
        if (!userSnapshot) {
          console.warn(`⚠️ 用户 ${userId} 未在 active user_staking 中找到。`)
        } else {
          console.log(`
📄 用户 ${userId} 当前发放快照：`)
          console.log(`  已发次数    : ${userSnapshot.dailyDistributionCount}/${status.distributionCount}`)
          console.log(`  当日总收益  : ${userSnapshot.currentDailyReward.toFixed(4)} NEAR`)
          console.log(`  已发金额    : ${userSnapshot.dailyRewardDistributed.toFixed(4)} NEAR`)
          console.log(`  下一次发放  : ${userSnapshot.nextDistributionAt ? formatBeijingTime(userSnapshot.nextDistributionAt) : '未安排'}`)
          console.log(`  最近结算时间: ${userSnapshot.lastSettlementDate ? formatBeijingTime(userSnapshot.lastSettlementDate) : '无'}`)

          const recentRewards = await prisma.stakingReward.findMany({
            where: { userId },
            orderBy: { createdAt: 'desc' },
            take: 5
          })

          console.log(`  最近 5 条 staking_rewards：`)
          recentRewards.forEach((reward, index) => {
            console.log(
              `    [${index + 1}] ${formatBeijingTime(reward.createdAt)} | ` +
              `${Number(reward.amount).toFixed(4)} NEAR | key=${reward.distributionKey ?? 'null'}`
            )
          })
        }
      }
    }

    console.log('\n✅ 查询完成，未对数据库做任何修改。')
  } catch (error) {
    console.error('❌ 检测过程出现错误:', error)
    process.exitCode = 1
  } finally {
    await prisma.$disconnect()
  }
}

void main()
